在 Qt 开发中使用 less 简化 css 维护工作

1. 概述

1.1. 使用CSS遇到的问题

  • 多皮肤 CSS 信息冗余. 程序往往有多套皮肤, 而每套皮肤都对应至少一个 CSS, 随着皮肤的增多, 多套CSS的维护成本变得很高. 让我们想想这样一个场景, 设计部对现有皮肤的某一样式做了修改, 我们就得在每套皮肤的CSS中找到该样式的位置, 再一个一个进行修改. 在整个过程中, 有很大部分的时间浪费在了查找和切换文件这些事情上了.
  • CSS 注释不友好, 其只支持/* */ 格式的注释. 但是这样的注释又无法嵌套, 所以我们通常是不写注释的. CSS 文件内容越多, 就越像天书. 而且很多样式是试验多次后得出的最佳效果, 一旦改了其中一个值, 可能就会有其他令人匪夷所思的问题.

1.2. Less简介

  • Less 是一种 CSS 预处理语言.
  • Less 基于 node.js
  • Less 比 CSS 多了变量, Mixin, 可调用的原生函数, 分支语句, 循环语句 等支持. 可以把原本杂乱的 CSS 整理得更加简短和易于维护.

2. 解决多皮肤样式表冗余问题

  • 需要用到的 less 特性
    • Less 变量值可以为数组, 使用时可配合 extract() 获取数组指定 index 的值.
    • Less 可以在调用 lessc 时, 通过命令行参数--modify-var="变量名=值"来修改 less 文件中的变量值.

假设有 blue.css, red.css, white.css 三个 css, 且以最简单的 QPushButton 样式为例.

2.1. 未使用Less前

  • 在各样式表中分别编写, 维护时也得在各样式表中查找, 修改.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* blue.css 文件中 */
.QPushButton {
min-height: 20px;
max-height: 20px;

color: white;
background-color: #0a0914;
}

/* red.css 文件中 */
.QPushButton {
min-height: 20px;
max-height: 20px;
color: white;
background-color: #170B0C;
}

/* white.css 文件中 */
.QPushButton {
min-height: 20px;
max-height: 20px;
color: black;
background-color: #white;
}

2.2. 使用less后

  1. 编写 main.less

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // main.less
    @skin_blue: 1;
    @skin_red: 2;
    @skin_white: 3;

    @mainCol: white, white, black;
    @mainBkColor: #0a0914, #170B0C, white;

    // 当前皮肤颜色, 这个值可以在外部修改, 从而改变 @crtSkinIndex 的值
    @crtSkinName: skin_blue;
    @crtSkinIndex: @@crtSkinName;

    // 举个例子, 给 QPushButton 设置样式
    .QPushButton {
    min-height: 20px;
    max-height: 20px;
    color: extract(@mainCol, @crtSkinIndex);
    background-color: extract(@mainBkColor, @crtSkinIndex);
    }
  2. 执行以下命令, 生成各css: ( 修改 less 文件中的 crtSkinName 变量值 )

    1
    2
    3
    lessc main.less blue.css `--modify-var="crtSkinName=skin_blue"`
    lessc main.less red.css `--modify-var="crtSkinName=skin_red"`
    lessc main.less white.css `--modify-var="crtSkinName=skin_white"`
  3. 得到各 css 文件.

3. QSS中url()路径拼接问题

  • less 中会将 rgba(), url() 等当做函数处理, 但我们不想让它这么做, 可以使用 ~"" 转义.
  • 要对 url() 中的路径进行拼接时, 需要使用字符串拼接函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 使用 %("%s %d", "123", 10) 实现字符串替换. 且当第一个参数为 ~"" 时, 最后生成的字符串无 引号
.Mixin_path(@filepath) {
@rtnVal: %(~"url(:/%s/Resources/%s)", @crtImgDir, @filepath);
}

.QCheckBox {
&{
color: extract(@mainCol, @crtSkinIndex);
}
&::indicator {
&:unchecked{
.Mixin_path(@filepath:~"checkbox_uc_n.png");
border-image: @rtnVal;
}
&:unchecked:hover {
.Mixin_path(@filepath:~"checkbox_uc_h.png");
border-image: @rtnVal;
}
&:checked{
.Mixin_path(@filepath:~"checkbox_c_na.png");
border-image: @rtnVal;
}
&:checked:hover {
.Mixin_path(@filepath:~"checkbox_c_h.png");
border-image: @rtnVal;
}
}
}

生成的 CSS 内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.QCheckBox {
color: white;
}
.QCheckBox::indicator:unchecked {
border-image: url(:/blue/Resources/checkbox_uc_n.png);
}
.QCheckBox::indicator:unchecked:hover {
border-image: url(:/blue/Resources/checkbox_uc_h.png);
}
.QCheckBox::indicator:checked {
border-image: url(:/blue/Resources/checkbox_c_na.png);
}
.QCheckBox::indicator:checked:hover {
border-image: url(:/blue/Resources/checkbox_c_h.png);
}

— 道理越辩越明, 欢迎留言讨论. —

0%